home *** CD-ROM | disk | FTP | other *** search
/ Clickx 96 / Clickx 96.iso / software / tools / tool / xbmc-10.1.exe / addons / webinterface.default / js / NowPlayingManager.js < prev   
Encoding:
JavaScript  |  2011-03-08  |  18.3 KB  |  482 lines

  1. /*
  2.  *      Copyright (C) 2005-2010 Team XBMC
  3.  *      http://www.xbmc.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with XBMC; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21.  
  22. var NowPlayingManager = function() {
  23.         this.init();
  24.         return true;
  25.     }
  26.  
  27. NowPlayingManager.prototype = {
  28.         updateCounter: 0,
  29.         init: function() {
  30.             $('#pbPause').hide(); /* Assume we are not playing something */
  31.             this.bindPlaybackControls();
  32.             this.updateState();
  33.             $('#nextTrack').bind('click', jQuery.proxy(this.showPlaylist, this));
  34.             $('#nowPlayingPlaylist').bind('click', function() {return false;});
  35.             $(window).bind('click', jQuery.proxy(this.hidePlaylist, this));
  36.         },
  37.         updateState: function() {
  38.             jQuery.ajax({
  39.                 type: 'POST', 
  40.                 url: JSON_RPC + '?UpdateState', 
  41.                 data: '{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}', 
  42.                 timeout: 2000,
  43.                 success: jQuery.proxy(function(data) {
  44.                     if (data && data.result) {
  45.                         if (data.result.audio && this.activePlayer != 'Audio') {
  46.                             this.activePlayer = 'Audio';
  47.                             this.stopVideoPlaylistUpdate();
  48.                             this.displayAudioNowPlaying();
  49.                             this.stopRefreshTime();
  50.                         } else if (data.result.video && this.activePlayer != 'Video') {
  51.                             this.activePlayer = 'Video';
  52.                             this.stopAudioPlaylistUpdate();
  53.                             this.displayVideoNowPlaying();
  54.                             this.stopRefreshTime();
  55.                         } else if (!data.result.audio && !data.result.video) {
  56.                             this.stopRefreshTime();
  57.                         }
  58.                     }
  59.                     setTimeout(jQuery.proxy(this.updateState, this), 1000);
  60.                 }, this),
  61.                 error: jQuery.proxy(function(data, error) {
  62.                     displayCommunicationError();
  63.                     setTimeout(jQuery.proxy(this.updateState, this), 2000);
  64.                 }, this), 
  65.                 dataType: 'json'});
  66.         },
  67.         bindPlaybackControls: function() {
  68.             $('#pbNext').bind('click', jQuery.proxy(this.nextTrack, this));
  69.             $('#pbPrev').bind('click', jQuery.proxy(this.prevTrack, this));
  70.             $('#pbStop').bind('click', jQuery.proxy(this.stopTrack, this));
  71.             $('#pbPlay').bind('click', jQuery.proxy(this.playPauseTrack, this));
  72.             $('#pbPause').bind('click', jQuery.proxy(this.playPauseTrack, this));
  73.         },
  74.         showPlaylist: function() {
  75.             $('#nextText').html('Playlist: ');
  76.             $('#nowPlayingPlaylist').show();
  77.             return false;
  78.         },
  79.         hidePlaylist: function() {
  80.             $('#nextText').html('Next: ');
  81.             $('#nowPlayingPlaylist').hide();
  82.             return false;
  83.         },
  84.         nextTrack: function() {
  85.             if (this.activePlayer) {
  86.                 jQuery.post(JSON_RPC + '?SkipNext', '{"jsonrpc": "2.0", "method": "' + this.activePlayer + 'Player.SkipNext", "id": 1}', jQuery.proxy(function(data) {
  87.                     if (data && data.result == 'OK') {
  88.                         //this.updateAudioPlaylist(true);
  89.                     }
  90.                 }, this), 'json');
  91.             }
  92.         },
  93.         prevTrack: function() {
  94.             if (this.activePlayer) {
  95.                 jQuery.post(JSON_RPC + '?SkipPrevious', '{"jsonrpc": "2.0", "method": "' + this.activePlayer + 'Player.SkipPrevious", "id": 1}', jQuery.proxy(function(data) {
  96.                     if (data && data.result == 'OK') {
  97.                         //this.updateAudioPlaylist(true);
  98.                     }
  99.                 }, this), 'json');
  100.             }
  101.         },
  102.         stopTrack: function() {
  103.             if (this.activePlayer) {
  104.                 jQuery.post(JSON_RPC + '?Stop', '{"jsonrpc": "2.0", "method": "' + this.activePlayer + 'Player.Stop", "id": 1}', jQuery.proxy(function(data) {
  105.                     if (data && data.result == 'OK') {
  106.                         this.playing = false;
  107.                         this.paused = false;
  108.                         this.trackBaseTime = 0;
  109.                         this.showPlayButton();
  110.                     }
  111.                 }, this), 'json');
  112.             }
  113.         },
  114.         playPauseTrack: function() {
  115.             if (this.activePlayer) {
  116.                 var method = this.activePlayer + ((this.playing || this.paused) ? 'Player.PlayPause' : 'Playlist.Play');
  117.                 jQuery.post(JSON_RPC + '?PlayPause', '{"jsonrpc": "2.0", "method": "' + method + '", "id": 1}', jQuery.proxy(function(data) {
  118.                     if (data && data.result) {
  119.                         this.playing = data.result.playing;
  120.                         this.paused = data.result.paused;
  121.                         if (this.playing) {
  122.                             this.showPauseButton();
  123.                         } else {
  124.                             this.showPlayButton();
  125.                         }
  126.                     }
  127.                 }, this), 'json');
  128.             }
  129.         },
  130.         showPauseButton: function() {
  131.             $('#pbPause').show();
  132.             $('#pbPlay').hide();
  133.         },
  134.         showPlayButton: function() {
  135.             $('#pbPause').hide();
  136.             $('#pbPlay').show();
  137.         },
  138.         displayAudioNowPlaying: function() {
  139.             if (!this.autoRefreshAudioPlaylist) {
  140.                 this.autoRefreshAudioPlaylist = true;
  141.                 this.updateAudioPlaylist();
  142.             }
  143.         },
  144.         displayVideoNowPlaying: function() {
  145.             if (!this.autoRefreshVideoPlaylist) {
  146.                 this.autoRefreshVideoPlaylist = true;
  147.                 this.updateVideoPlaylist();
  148.             }
  149.         },
  150.         playPlaylistItem: function(sender) {
  151.             var sequenceId = $(sender.currentTarget).attr('seq');
  152.             if (!this.activePlaylistItem || (this.activePlaylistItem !== undefined && sequenceId != this.activePlaylistItem.seq)) {
  153.                 jQuery.post(JSON_RPC + '?PlaylistItemPlay', '{"jsonrpc": "2.0", "method": "' + this.activePlayer + 'Playlist.Play", "params": ' + sequenceId + ', "id": 1}', function() {}, 'json');
  154.             }
  155.             this.hidePlaylist();
  156.         },
  157.         playlistChanged: function(newPlaylist) {
  158.             if (this.activePlaylist && !newPlaylist || !this.activePlaylist && newPlaylist) {
  159.                 return true;
  160.             }
  161.             if (!this.activePlaylist && !newPlaylist) {
  162.                 return false;
  163.             }
  164.             if (this.activePlaylist.length != newPlaylist.length) {
  165.                 return true;
  166.             }
  167.             for (var i = 0; i < newPlaylist.length; i++) {
  168.                 if (!this.comparePlaylistItems(this.activePlaylist[i], newPlaylist[i])) {
  169.                     return true;
  170.                 }
  171.             }
  172.             return false;
  173.         },
  174.         updateAudioPlaylist: function() {
  175.             jQuery.ajax({
  176.                 type: 'POST', 
  177.                 url: JSON_RPC + '?updateAudioPlaylist', 
  178.                 data: '{"jsonrpc": "2.0", "method": "AudioPlaylist.GetItems", "params": { "fields": ["title", "album", "artist", "duration"] }, "id": 1}', 
  179.                 success: jQuery.proxy(function(data) {
  180.                     if (data && data.result && data.result.items && data.result.total > 0) {
  181.                         //Compare new playlist to active playlist, only redraw if a change is noticed
  182.                         if (!this.activePlaylistItem || this.playlistChanged(data.result.items) || (this.activePlaylistItem && (this.activePlaylistItem.seq != data.result.current))) {
  183.                             var ul = $('<ul>');
  184.                             var activeItem;
  185.                             $.each($(data.result.items), jQuery.proxy(function(i, item) {
  186.                                 var li = $('<li>');
  187.                                 var code = '<span class="duration">' + durationToString(item.duration) + '</span><div class="trackInfo" title="' + item.title + ' - ' + item.artist + '"><span class="trackTitle">' + item.title + '</span> - <span class="trackArtist">' + item.artist + '</span></div>';
  188.                                 if (i == data.result.current) {
  189.                                     activeItem = item;
  190.                                     activeItem.seq = i;
  191.                                     li.addClass('activeItem');
  192.                                 }
  193.                                 if (i == (data.result.current + 1)) {
  194.                                     $('#nextTrack').html(code).show();
  195.                                 }
  196.                                 li.bind('click', jQuery.proxy(this.playPlaylistItem, this));
  197.                                 ul.append(li.attr('seq', i).html(code));
  198.                             }, this));
  199.                             if (data.result.total > 1) {
  200.                                 if (activeItem && data.result.total-1 == activeItem.seq) {
  201.                                     $('#nextTrack').html('<div class="trackInfo">Last track in playlist</div>').show();
  202.                                 }
  203.                                 $('#nextText').show();
  204.                                 $('#nowPlayingPlaylist').html('').append(ul);
  205.                             } else {
  206.                                 $('#nextText').hide();
  207.                                 $('#nowPlayingPlaylist').hide();
  208.                                 $('#nextTrack').hide();
  209.                             }
  210.                             if (!this.comparePlaylistItems(activeItem, this.activePlaylistItem)) {
  211.                                 this.activePlaylistItem = activeItem;
  212.                                 if (!this.updateActiveItemDurationRunOnce) {
  213.                                     this.updateActiveItemDurationRunOnce = true;
  214.                                     this.updateActiveItemDuration();
  215.                                 }
  216.                             } else if (!activeItem) {
  217.                                 this.stopRefreshTime();
  218.                             }
  219.                             this.activePlaylist = data.result.items;
  220.                             $('#videoDescription').hide();
  221.                             $('#audioDescription').show();
  222.                             $('#nowPlayingPanel').show();
  223.                         }
  224.                     } else {
  225.                         this.activePlaylist = null;
  226.                         $('#audioDescription').hide();
  227.                         $('#nowPlayingPanel').hide();
  228.                     }
  229.                     if (this.autoRefreshAudioPlaylist) {
  230.                         setTimeout(jQuery.proxy(this.updateAudioPlaylist, this), 1000);
  231.                     }
  232.                 }, this),
  233.                 error: jQuery.proxy(function(data) {
  234.                     displayCommunicationError();
  235.                     if (this.autoRefreshAudioPlaylist) {
  236.                         setTimeout(jQuery.proxy(this.updateAudioPlaylist, this), 2000); /* Slow down request period */
  237.                     }
  238.                 }, this),
  239.                 dataType: 'json'
  240.             });
  241.         },
  242.         stopAudioPlaylistUpdate: function() {
  243.             this.autoRefreshAudioPlaylist = false;
  244.             this.updateActiveItemDurationRunOnce = false;
  245.         },
  246.         stopVideoPlaylistUpdate: function() {
  247.             this.autoRefreshVideoPlaylist = false;
  248.             this.updateActiveItemDurationRunOnce = false;
  249.         },
  250.         updateActiveItemDurationLoop: function() {
  251.             this.activeItemTimer = 0;
  252.             this.updateActiveItemDuration();
  253.         },
  254.         updateActiveItemDuration: function() {
  255.             jQuery.post(JSON_RPC + '?updateDuration', '{"jsonrpc": "2.0", "method": "' + this.activePlayer + 'Player.GetTime", "id": 1}', jQuery.proxy(function(data) {
  256.                 if (data && data.result) {
  257.                     this.trackBaseTime = data.result.time;
  258.                     this.playing = data.result.playing;
  259.                     this.paused = data.result.paused;
  260.                     if (!this.autoRefreshAudioData && !this.autoRefreshVideoData) {
  261.                         if (data.result.playing) {                
  262.                             if (this.activePlayer == 'Audio') {
  263.                                 this.autoRefreshAudioData = true;
  264.                                 this.refreshAudioData();
  265.                             } else if (this.activePlayer == 'Video') {
  266.                                 this.autoRefreshVideoData = true;
  267.                                 this.refreshVideoData();
  268.                             }
  269.                         }
  270.                     }
  271.                 }
  272.                 if ((this.autoRefreshAudioData || this.autoRefreshVideoData) && !this.activeItemTimer) {
  273.                     this.activeItemTimer = 1;
  274.                     setTimeout(jQuery.proxy(this.updateActiveItemDurationLoop, this), 1000);
  275.                 }
  276.             }, this), 'json');
  277.         },
  278.         refreshAudioDataLoop: function() {
  279.             this.audioRefreshTimer = 0;
  280.             this.refreshAudioData();
  281.         },
  282.         refreshAudioData: function() {
  283.             if (this.autoRefreshAudioData && !this.audioRefreshTimer) {
  284.                 this.audioRefreshTimer = 1;
  285.                 setTimeout(jQuery.proxy(this.refreshAudioDataLoop, this), 1000);
  286.             }
  287.             if (this.playing && !this.paused) {
  288.                 this.trackBaseTime++;
  289.             }
  290.             if (this.paused) {
  291.                 this.showPlayButton();
  292.             } else if (this.playing) {
  293.                 this.showPauseButton();
  294.             }
  295.             if (this.activePlaylistItem) {
  296.                 if (this.activePlaylistItem != this.lastPlaylistItem) {
  297.                     this.lastPlaylistItem = this.activePlaylistItem;
  298.                     var imgPath = DEFAULT_ALBUM_COVER;
  299.                     if (this.activePlaylistItem.thumbnail) {
  300.                         imgPath = (this.activePlaylistItem.thumbnail.startsWith('special://') ? '/vfs/' : 'images/') + this.activePlaylistItem.thumbnail;
  301.                     }
  302.                     $('#audioCoverArt').html('<img src="' + imgPath + '" alt="' + this.activePlaylistItem.album + ' cover art">');
  303.                     $('#audioTrackTitle').html('<span title="' + this.activePlaylistItem.title + '">' + this.activePlaylistItem.title + '</span>');
  304.                     if (this.activePlaylistItem.album) {
  305.                         $('#audioAlbumTitle').html('<span title="' + this.activePlaylistItem.album + '">' + this.activePlaylistItem.album + '</span>')
  306.                                              .show();
  307.                     } else {
  308.                         $('#audioAlbumTitle').hide();
  309.                     }
  310.                     $('#audioArtistTitle').html(this.activePlaylistItem.artist);
  311.                     $('#progressBar').attr('style', '');
  312.                 }
  313.                 $('#audioDuration').html(durationToString(this.trackBaseTime) + ' / ' + durationToString(this.activePlaylistItem.duration));
  314.                 var buttonWidth = $('#progressBar .progressIndicator').width();
  315.                 var progressBarWidth = (this.trackBaseTime / this.activePlaylistItem.duration) * 100;
  316.                 var progressSliderPosition = Math.ceil(($('#progressBar').width() / 100) * progressBarWidth) - buttonWidth;
  317.                 if (progressSliderPosition < 0) {
  318.                     progressSliderPosition = 0;
  319.                 }
  320.                 if (progressBarWidth <= 100) {
  321.                     $('#progressBar .elapsedTime').width(progressBarWidth + '%');
  322.                     $('#progressBar .progressIndicator').css('left', progressSliderPosition);
  323.                 }
  324.             }
  325.         },
  326.         refreshVideoDataLoop: function() {
  327.             this.videoRefreshTimer = 0;
  328.             this.refreshVideoData();
  329.         },
  330.         refreshVideoData: function() {
  331.             if (this.autoRefreshVideoData && !this.videoRefreshTimer) {
  332.                 this.videoRefreshTimer = 1;
  333.                 setTimeout(jQuery.proxy(this.refreshVideoDataLoop, this), 1000);
  334.             }
  335.             if (this.playing && !this.paused) {
  336.                 this.trackBaseTime++;
  337.             }
  338.             if (this.paused) {
  339.                 this.showPlayButton();
  340.             } else if (this.playing) {
  341.                 this.showPauseButton();
  342.             }
  343.             if (this.activePlaylistItem) {
  344.                 if (this.activePlaylistItem != this.lastPlaylistItem) {
  345.                     this.lastPlaylistItem = this.activePlaylistItem;
  346.                     var imgPath = DEFAULT_VIDEO_COVER;
  347.                     if (this.activePlaylistItem.thumbnail) {
  348.                         imgPath = (this.activePlaylistItem.thumbnail.startsWith('special://') ? '/vfs/' : 'images/') + this.activePlaylistItem.thumbnail;
  349.                     }
  350.                     $('#videoCoverArt').html('<img src="' + imgPath + '" alt="' + this.activePlaylistItem.title + ' cover art">');
  351.                     var imgWidth = $('#videoCoverArt img').width();
  352.                     $('#progressBar').width(365 - (imgWidth - 100));
  353.                     $('#videoTrackWrap').width(365 - (imgWidth - 100));
  354.                     $('#videoTitle').width(365 - (imgWidth - 100));
  355.                     $('#videoShowTitle').html(this.activePlaylistItem.showtitle||' ');
  356.                     var extra = '';
  357.                     if (this.activePlaylistItem.season && this.activePlaylistItem.episode) {
  358.                         extra = this.activePlaylistItem.season + 'x' + this.activePlaylistItem.episode + ' ';
  359.                     }
  360.                     $('#videoTitle').html(extra + this.activePlaylistItem.title);
  361.                 }
  362.                 $('#videoDuration').html(durationToString(this.trackBaseTime) + ' / ' + durationToString(this.activePlaylistItem.duration));
  363.                 var buttonWidth = $('#progressBar .progressIndicator').width();
  364.                 var progressBarWidth = (this.trackBaseTime / this.activePlaylistItem.duration) * 100;
  365.                 var progressSliderPosition = Math.ceil(($('#progressBar').width() / 100) * progressBarWidth) - buttonWidth;
  366.                 if (progressSliderPosition < 0) {
  367.                     progressSliderPosition = 0;
  368.                 }
  369.                 if (progressBarWidth <= 100) {
  370.                     $('#progressBar .elapsedTime').width(progressBarWidth + '%');
  371.                     $('#progressBar .progressIndicator').css('left', progressSliderPosition);
  372.                 }
  373.             }
  374.         },
  375.         stopRefreshTime: function() {
  376.             this.autoRefreshAudioData = false;
  377.             this.autoRefreshVideoData = false;
  378.         },
  379.         comparePlaylistItems: function(item1, item2) {
  380.             if (!item1 || !item2) {
  381.                 if (!item1 && !item2) {
  382.                     return true;
  383.                 }
  384.                 return false;
  385.             }
  386.             if (item1.title != item2.title) {
  387.                 return false;
  388.             }
  389.             if (item1.album != item2.album) {
  390.                 return false;
  391.             }
  392.             if (item1.artist != item2.artist) {
  393.                 return false;
  394.             }
  395.             if (item1.duration != item2.duration) {
  396.                 return false;
  397.             }
  398.             if (item1.label != item2.label) {
  399.                 return false;
  400.             }
  401.             if (item1.season != item2.season) {
  402.                 return false;
  403.             }
  404.             if (item1.episode != item2.episode) {
  405.                 return false;
  406.             }
  407.             return true;
  408.         },
  409.         updateVideoPlaylist: function() {
  410.             jQuery.ajax({
  411.                 type: 'POST', 
  412.                 url: JSON_RPC + '?updateVideoPlaylist', 
  413.                 data: '{"jsonrpc": "2.0", "method": "VideoPlaylist.GetItems", "params": { "fields": ["title", "season", "episode", "plot", "duration", "showtitle"] }, "id": 1}', 
  414.                 success: jQuery.proxy(function(data) {
  415.                     if (data && data.result && data.result.items && data.result.total > 0) {
  416.                         //Compare new playlist to active playlist, only redraw if a change is noticed.
  417.                         if (this.playlistChanged(data.result.items)) {
  418.                             var ul = $('<ul>');
  419.                             var activeItem;
  420.                             $.each($(data.result.items), jQuery.proxy(function(i, item) {
  421.                                 var li = $('<li>');
  422.                                 var extra = '';
  423.                                 if (item.season && item.episode) {
  424.                                     extra = item.season + 'x' + item.episode + ' ';
  425.                                 }
  426.                                 var code = '<span class="duration">' + durationToString(item.duration) + '</span><div class="trackInfo" title="' + extra + item.title + '"><span class="trackTitle">' + extra + item.title + '</span></div>';
  427.                                 if (i == data.result.current) {
  428.                                     activeItem = item;
  429.                                     activeItem.seq = i;
  430.                                     li.addClass('activeItem');
  431.                                 }
  432.                                 if (i == (data.result.current + 1)) {
  433.                                     $('#nextTrack').html(code).show();
  434.                                 }
  435.                                 li.bind('click', jQuery.proxy(this.playPlaylistItem, this));
  436.                                 ul.append(li.attr('seq', i).html(code));
  437.                             }, this));
  438.                             if (data.result.total > 1) {
  439.                                 $('#nextText').show();
  440.                                 if (activeItem && data.result.total == activeItem.seq) {
  441.                                     $('#nextTrack').html('<div class="trackInfo">Last track in playlist</div>').show();
  442.                                 }
  443.                                 $('#nowPlayingPlaylist').html('').append(ul);
  444.                             } else {
  445.                                 $('#nextText').hide();
  446.                                 $('#nowPlayingPlaylist').hide();
  447.                                 $('#nextTrack').hide();
  448.                             }
  449.                             if (!this.comparePlaylistItems(activeItem, this.activePlaylistItem)) {
  450.                                 this.activePlaylistItem = activeItem;
  451.                                 if (!this.updateActiveItemDurationRunOnce) {
  452.                                     this.updateActiveItemDurationRunOnce = true;
  453.                                     this.updateActiveItemDuration();
  454.                                 }
  455.                             } else if (!activeItem) {
  456.                                 this.stopRefreshTime();
  457.                             }
  458.                             this.activePlaylist = data.result.items;
  459.                             $('#videoDescription').show();
  460.                             $('#audioDescription').hide();
  461.                             $('#nowPlayingPanel').show();
  462.                         }
  463.                     } else {
  464.                         this.activePlaylist = null;
  465.                         $('#videoDescription').hide();
  466.                         $('#nowPlayingPanel').hide();
  467.                     }                    
  468.                     if (this.autoRefreshVideoPlaylist) {
  469.                         setTimeout(jQuery.proxy(this.updateVideoPlaylist, this), 1000);
  470.                     }
  471.                 }, this),
  472.                 error: jQuery.proxy(function(data) {
  473.                     displayCommunicationError();
  474.                     if (this.autoRefreshVideoPlaylist) {
  475.                         setTimeout(jQuery.proxy(this.updateVideoPlaylist, this), 2000); /* Slow down request period */
  476.                     }
  477.                 }, this),
  478.                 dataType: 'json'
  479.             });
  480.         }
  481.     }
  482.